#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->download_progressBar->hide();
    open_flag = 0;
    start_flag = 0;
    packet_id = 0;
    timer.start(1000);
    connect(&timer, SIGNAL(timeout()), this, SLOT(timerOut_slot()));
    connect(&serial, SIGNAL(readyRead()), this, SLOT(read_serial_slot()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::timerOut_slot(void)
{
    QStringList serial_Name_temp_list;

    if(open_flag == 1)
        return;

    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        serial_Name_temp_list << info.portName();
    }

    if(serial_Name_temp_list != serial_Name_list)
    {
        ui->serial_number_comboBox->clear();
        serial_Name_list = serial_Name_temp_list;
        ui->serial_number_comboBox->addItems(serial_Name_list);
    }
}

void MainWindow::on_serial_open_pushButton_clicked()
{
    if(open_flag == 0)
    {
        serial.setPortName(ui->serial_number_comboBox->currentText());
        serial.setBaudRate(ui->baud_rate_comboBox->currentText().toInt());
        switch(ui->parity_bit_comboBox->currentIndex())
        {
            case 0:
                serial.setParity(QSerialPort::NoParity); break;
            case 1:
                serial.setParity(QSerialPort::OddParity); break;
            case 2:
                serial.setParity(QSerialPort::EvenParity); break;
            case 3:
                serial.setParity(QSerialPort::MarkParity); break;
            case 4:
                serial.setParity(QSerialPort::SpaceParity); break;
            default:
                break;
        }
        switch(ui->data_bit_comboBox->currentIndex())
        {
            case  0:
                serial.setDataBits(QSerialPort::Data5); break;
            case  1:
                serial.setDataBits(QSerialPort::Data6); break;
            case  2:
                serial.setDataBits(QSerialPort::Data7); break;
            case  3:
                serial.setDataBits(QSerialPort::Data8); break;
            default:
                break;
        }
        switch(ui->stop_bit_comboBox->currentIndex())
        {
        case  0:
            serial.setStopBits(QSerialPort::OneStop); break;
        case  1:
            serial.setStopBits(QSerialPort::OneAndHalfStop); break;
        case  2:
            serial.setStopBits(QSerialPort::TwoStop); break;
        default:
            break;
        }
        serial.setFlowControl(QSerialPort::NoFlowControl);
        if(serial.open(QIODevice::ReadWrite) == true)
        {
            open_flag = 1;
            ui->serial_open_pushButton->setText(QString("关闭"));
            qDebug()<<"open success";
        }
        else
        {
            QMessageBox::warning(NULL, "warning", "串口不存在或者被其它应用程序占用！", "确定");
            qDebug()<<"open failed";
        }
    }
    else
    {
        serial.close();
        ui->serial_open_pushButton->setText(QString("打开"));
        open_flag = 0;
        qDebug()<<"close success";
    }
}

void MainWindow::on_open_file_pushButton_clicked()
{
  QString path = QFileDialog::getOpenFileName(this, tr("Open File"), ".", tr("Bin Files(*.bin)"));
  if(path.isNull())
      return;

  ui->file_name_lineEdit->setText(path);
  QFile file(path);
  file.open(QIODevice::ReadWrite);
  QByteArray array = file.readAll();
  file_len = array.size();
  tx_data = array.data();
  write_index = 0;
  ui->download_progressBar->setValue(write_index/file_len);
}

/* 点击烧录按钮槽函数 */
void MainWindow::on_download_pushButton_clicked()
{
    /* 烧录之前必须打开串口 */
    if(open_flag == 0)
    {
        QMessageBox::warning(NULL, "warning", "请打开串口！", "确定");
        return;
    }

    /* 烧录之前必须选择烧录文件 */
    if(ui->file_name_lineEdit->text().isEmpty())
    {
        QMessageBox::warning(NULL, "warning", "请选择需要烧录的文件！", "确定");
        return;
    }

    /* 烧录按钮变灰 */
    ui->download_pushButton->setEnabled(false);

    /* 显示进度条 */
    ui->download_progressBar->show();
    ui->download_progressBar->setValue(0);

    /* 写入的字节偏移量为0 */
    write_index = 0;

    /* 发送进入bootloader命令 */
    send_bootloader();

    /* 刷机开始 */
    start_flag = 1;
}

#include <iostream>

/* 串口写入函数 */
void MainWindow::serial_write(unsigned char *buf, int len)
{
    packet_id++;
    if(packet_id == 63)
        packet_id = 0;

    buf[4] = packet_id;
    printf("write_serial_%d[", len);
    for(int i = 0; i < len; i++)
        printf("%x ", buf[i]);
    printf("]\n");
    std::cout.flush();

    serial.write((const char *)buf, len);
}

/* 发送bootloader */
void MainWindow::send_bootloader(void)
{
    /* 进入BootLoader */
    unsigned char buf[10] = {0xEA, 0xEB, 0xEE, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0A};

    serial_write(buf, 10);
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    int nRet = QMessageBox::question(NULL, "Confirm", "确认退出？", "是", "否");
    if(1 == nRet)
        event->ignore();
}

/* 校验cmd */
int MainWindow::check_cmd(unsigned char *buf, int len)
{
    int flag = 0;

    printf("read_serial_%d[", len);
    for(int i = 0; i < len; i++)
        printf("%x ", buf[i]&0xFF);
    printf("]\n");
    std::cout.flush();

    if(buf[0] == 0xEA && buf[1] == 0xEB && buf[2] == 0xEE)
    {
        if(buf[3] == len - 6)
        {
            if(buf[len-2] == 0x0D && buf[len-1] == 0x0A)
            {
                flag = 1;
            }
        }
    }

    if(flag == 0)
    {
        start_flag = 0;
        write_index = 0;
        ui->download_progressBar->setValue(0);
        ui->download_progressBar->hide();
        QMessageBox::warning(NULL, "warning", "烧录失败！", "确定");
        ui->download_pushButton->setEnabled(true);
        return 0;
    }

    return 1;
}

/* 校验ack */
int MainWindow::check_ack(unsigned char *buf)
{
    int flag = 0;

    if((buf[4]&0x3F) == packet_id)
        flag = 1;

    if(flag == 0)
    {
        start_flag = 0;
        write_index = 0;
        ui->download_progressBar->setValue(0);
        ui->download_progressBar->hide();
        QMessageBox::warning(NULL, "warning", "烧录失败！", "确定");
        ui->download_pushButton->setEnabled(true);
        return 0;
    }

    return 1;
}

/* 烧录 */
void MainWindow::send_download(void)
{


}

void MainWindow::read_serial_slot(void)
{
    QByteArray read_array;
    char *rx_data;
    int len;

    read_array = serial.readAll();

    rx_data = read_array.data();
    len = read_array.size();

    if(start_flag == 0)
        return;

    /* 校验命令 */
    if(check_cmd((unsigned char *)rx_data, len) == 0)
        return;

    int protocol;
    protocol = rx_data[5];
    unsigned char buf[50] = {0xEA, 0xEB, 0xEE, 0x2C ,0x00, 0x02, 0x00, 0x00};
    uint16_t CheckSum = 0;



    switch(protocol)
    {
        case 0:
            if(check_ack((unsigned char *)rx_data) == 0)
                return;
            break;

        case 1:
//            send_download();

            write_index = 0;
            buf[48] = 0x0D;
            buf[49] = 0x0A;
            buf[8] = write_index / 256;
            buf[9] = write_index % 256;
            memcpy(buf + 10, tx_data + write_index, 36);
            for(int j = 0; j < 36; j++)
            {
                CheckSum +=  buf[10 + j];
            }
            buf[46] = CheckSum / 256;
            buf[47] = CheckSum % 256;
            serial.write((const char *)buf, 50);
            break;

        case 2:
            write_index+=36;
            if(write_index <= file_len)
                ui->download_progressBar->setValue(write_index*100/file_len);
            else
                ui->download_progressBar->setValue(100);

            if(write_index < file_len)
            {
                int tx_len;

                if(write_index+36>file_len)
                {
                    tx_len = file_len-write_index;
                    buf[3] = 8 + tx_len;
                }
                else
                    tx_len = 36;

                buf[12+tx_len] = 0x0D;
                buf[13+tx_len] = 0x0A;
                buf[8] = write_index / 256;
                buf[9] = write_index % 256;
                memcpy(buf + 10, tx_data + write_index, tx_len);
                for(int j = 0; j < tx_len; j++)
                {
                    CheckSum +=  buf[10 + j];
                }
                buf[10+tx_len] = CheckSum / 256;
                buf[11+tx_len] = CheckSum % 256;

                serial.write((const char *)buf, 14+tx_len);
            }
            else
            {
                /* 启动APP */
                unsigned char buf1[10] = {0xEA, 0xEB, 0xEE, 0x04, 0x00, 0x03, 0x00, 0x00, 0x0D, 0x0A};
                serial.write((const char *)buf1, 10);
            }
            break;

        case 3:
            start_flag = 0;
            write_index = 0;
            ui->download_progressBar->setValue(0);
            ui->download_progressBar->hide();
            QMessageBox::information(NULL, "warning", "烧录成功！", "确定");
            ui->download_pushButton->setEnabled(true);
            break;

        default:
            break;
    }



}
